package com.xpalive.config.spring.exceptionhandle;

import com.xpalive.base.dto.result.RespFailure;
import com.xpalive.base.dto.result.RespResult;
import com.xpalive.commons.Constants.RespCode;
import com.xpalive.exception.BizException;
import java.text.MessageFormat;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
import lombok.extern.slf4j.Slf4j;
import org.springframework.dao.InvalidDataAccessResourceUsageException;
import org.springframework.validation.FieldError;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

/**
 * control 增强器 用于处理全局异常
 */
@RestControllerAdvice
@Slf4j
public class ControllerExceptionAdvice {

    @ExceptionHandler(value = Exception.class)
    public RespResult<String> errorHandler(Exception ex) {
        log.error(ex.getMessage(), ex);
        ex.getClass().getName();
        ex.getClass().getCanonicalName();
        return RespResult.ofFailure(RespCode.E500, ex);
    }

    @ExceptionHandler(value = BizException.class)
    public RespResult<String> errorHandler(BizException ex) {
        log.error(ex.getMessage(), ex);
        return RespResult.ofFailure(ex.getCode(), ex);
    }

    @ExceptionHandler(value = IllegalArgumentException.class)
    public RespResult<String> errorHandler(IllegalArgumentException ex) {
        log.error(ex.getMessage(), ex);
        return RespResult.ofFailure(RespCode.E400, "参数错误", ex);
    }

    @ExceptionHandler(value = InvalidDataAccessResourceUsageException.class)
    public RespResult<String> errorHandler(InvalidDataAccessResourceUsageException ex) {
        log.error(ex.getMessage(), ex);
        Throwable cause1 = ex.getCause();
        return RespResult.ofFailure(RespCode.E500, "无效的数据访问资源使用情况", ex);
    }

    @ExceptionHandler(MethodArgumentNotValidException.class)
    public RespResult<String> errorHander(
        MethodArgumentNotValidException ex) {
        log.error(ex.getMessage(), ex);
        final List<FieldError> fieldErrors = ex.getBindingResult().getFieldErrors();
        final RespResult<String> result = RespResult.ofFailure(RespCode.E400, "参数验证失败");
        List<RespFailure> respFailureList = fieldErrors.stream().map(fieldError -> {
            RespFailure failure = new RespFailure();
            failure.setBizMsg(fieldError.getDefaultMessage());
            failure.setBizCode(MessageFormat.format(
                "{0}.{1}", fieldError.getObjectName(),
                fieldError.getField()));
            return failure;
        }).collect(Collectors.toList());
        ObjectError globalError = ex.getBindingResult().getGlobalError();
        Optional.ofNullable(globalError).ifPresent(item -> {
            RespFailure failure = new RespFailure();
            failure.setBizCode(item.getObjectName());
            failure.setBizMsg(item.getDefaultMessage());
            respFailureList.add(failure);
        });
        result.setRespFailureList(respFailureList);
        return result;
    }
}
